Qt6 Example WebEngine Content Manipulation
介绍
Qt6 出了,使用 C++17,因此尝鲜一下。对 Qt 的 QWebEngine 很感兴趣,跑了一下使用 JQuery 的网页浏览 Demo。Qt 整体开发体验很不错,适合写一些严肃有深度的桌面程序。
CMake
CMake 内容如下:
cmake_minimum_required(VERSION 3.5)
project(WebEngineDemoManipulate VERSION 0.1 LANGUAGES CXX)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
find_package(Qt6 COMPONENTS Core)
find_package(Qt6 COMPONENTS Gui)
find_package(Qt6 COMPONENTS WebEngineWidgets)
find_package(Qt6 COMPONENTS Positioning REQUIRED)
find_package(Qt6 COMPONENTS PrintSupport)
set(PROJECT_SOURCES
main.cpp
mainwindow.cpp
mainwindow.h
)
qt_add_executable(WebEngineDemoManipulate
MANUAL_FINALIZATION
${PROJECT_SOURCES}
jquery.qrc
)
target_link_libraries(WebEngineDemoManipulate PRIVATE
Qt::Core
Qt::Gui
Qt::WebEngineWidgets
Qt::Positioning)
set_target_properties(WebEngineDemoManipulate PROPERTIES
MACOSX_BUNDLE_GUI_IDENTIFIER my.example.com
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
)
if(QT_VERSION_MAJOR EQUAL 6)
qt_finalize_executable(WebEngineDemoManipulate)
endif()
- 所使用到的 Qt Module,需要先 find_package,然后再放入到 link 中。
- WebEngine 对应的组件是 WebEngineWidgets,它还有依赖组件 Positioning 和 PrintSupport。其中 WebEngineWidgets 和 Positioning 都是附加模块,需要单独安装
- 在 Windows 下,Qt WebEngine 只支持使用 MSVS2019 构建,MinGW 8.1.0 是不包含这个模块的。
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QtWidgets>
QT_BEGIN_NAMESPACE
class QWebEngineView;
class QLineEdit;
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(const QUrl& url);
~MainWindow();
protected slots:
void adjustLocation();
void changeLocation();
void adjustTitle();
void setProgress(int p);
void finishLoad(bool);
void viewSource();
void highlightAllLinks();
void rotateImages(bool invert);
void removeGifImages();
void removeInlineFrames();
void removeObjectElements();
void removeEmbeddedElements();
private:
QString jQuery;
QWebEngineView *view;
QLineEdit *locationEdit;
QAction *rotateAction;
int progress;
};
#endif // MAINWINDOW_H
mainwindow.cpp
构造方法:
#include <QtWidgets>
#include <QtWebEngineWidgets>
#include <QDebug>
#include "mainwindow.h"
MainWindow::MainWindow(const QUrl& url) {
setAttribute(Qt::WA_DeleteOnClose, true);
progress = 0;
QFile file;
file.setFileName(":/jquery.min.js");
file.open(QIODevice::ReadOnly);
jQuery = file.readAll();
jQuery.append("\nvar qt = { 'jQuery': jQuery.noConflict(true) };");
file.close();
view = new QWebEngineView(this);
view->load(url);
connect(view, &QWebEngineView::loadFinished, this, &MainWindow::adjustLocation);
connect(view, &QWebEngineView::titleChanged, this, &MainWindow::adjustTitle);
connect(view, &QWebEngineView::loadProgress, this, &MainWindow::setProgress);
connect(view, &QWebEngineView::loadFinished, this, &MainWindow::finishLoad);
locationEdit = new QLineEdit(this);
locationEdit->setSizePolicy(
QSizePolicy::Expanding, locationEdit->sizePolicy().verticalPolicy());
connect(locationEdit, &QLineEdit::returnPressed, this, &MainWindow::changeLocation);
QToolBar *toolBar = addToolBar(tr("Navigation"));
toolBar->addAction(view->pageAction(QWebEnginePage::Back));
toolBar->addAction(view->pageAction(QWebEnginePage::Forward));
toolBar->addAction(view->pageAction(QWebEnginePage::Reload));
toolBar->addAction(view->pageAction(QWebEnginePage::Stop));
toolBar->addWidget(locationEdit);
QMenu *viewMenu = menuBar()->addMenu(tr("&Tools"));
QAction *viewSourceActoin = new QAction(tr("Page Source"), this);
connect(viewSourceActoin, &QAction::triggered, this, &MainWindow::viewSource);
viewMenu->addAction(viewSourceActoin);
viewMenu->addAction(tr("Highlight all links"), this, &MainWindow::highlightAllLinks);
rotateAction = new QAction(this);
rotateAction->setIcon(style()->standardIcon(QStyle::SP_FileDialogDetailedView));
rotateAction->setCheckable(true);
rotateAction->setText(tr("Turn Images upside and down"));
connect(rotateAction, &QAction::toggled, this, &MainWindow::rotateImages);
viewMenu->addAction(rotateAction);
viewMenu->addAction(tr("Remove GIF Images"), this, &MainWindow::removeGifImages);
viewMenu->addAction(tr("Remove all inline frames"), this, &MainWindow::removeInlineFrames);
viewMenu->addAction(tr("Remove all object elements"), this, &MainWindow::removeEmbeddedElements);
setCentralWidget(view);
}
- qrc 资源访问方式
加载完成执行 JS(JQuery):
void MainWindow::finishLoad(bool) {
progress = 100;
adjustTitle();
view->page()->runJavaScript(jQuery);
}
弹出新窗口查看源码:
void MainWindow::viewSource() {
QTextEdit *textEdit = new QTextEdit(nullptr);
textEdit->setAttribute(Qt::WA_DeleteOnClose);
textEdit->adjustSize();
textEdit->move(this->geometry().center() - textEdit->rect().center());
textEdit->show();
// view->page()->toHtml([textEdit](const QString & html) {
// textEdit->setPlainText(html);
// });
textEdit->setPlainText(jQuery);
}
将所有超链接高亮展示:
void MainWindow::highlightAllLinks() {
QString code = QStringLiteral("qt.jQuery('a').each(function() {qt.jQuery(this).css('background-color', 'yellow') })");
view->page()->runJavaScript(code, [](const QVariant & data) {
qInfo() << data;
});
}
添加资源文件
工程中使用到了 JQuery,将 jquery.min.js 放到项目根目录。
创建新文件 jquary.qrc,选择 Qt Resource,这是一个资源路径,前缀输入 /,再路径中添加 jquery.min.js。
将资源文件 jquary.qrc 添加到 cmake 当中。
IDE 使用技巧
- 切换头文件和源码文件 Shift+F2
- 切主题,Qt Creator Dark 很好看
- 字体 Cascadia Code SemiLight 很好看(尤其是斜体,有种手写的韵味,还有 -> 常用连写都没问题)
- 保存代码自动 Format,去帮助 Help 中装 Beautifier 插件,然后二进制连接到 Artistic Style,选择 Use customized style,输入:--style=google -p